package com.cencat.common.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.response.PageResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.function.Function;

/**
 * 统一分页查询工具类
 * 整合PageUtils和PageResponse功能，提供便捷的分页查询方法
 * 
 * @author cencat
 * @since 2024-01-01
 */

public class PaginationHelper {

    private static final Logger log = LoggerFactory.getLogger(PaginationHelper.class);

    /**
     * 私有构造函数，防止实例化
     */
    private PaginationHelper() {
        throw new UnsupportedOperationException("Utility class cannot be instantiated");
    }

    /**
     * 默认页码
     */
    public static final long DEFAULT_CURRENT = 1L;

    /**
     * 默认每页大小
     */
    public static final long DEFAULT_SIZE = 10L;

    /**
     * 最大每页大小
     */
    public static final long MAX_SIZE = 1000L;

    /**
     * 创建分页对象
     * 
     * @param current 当前页码
     * @param size 每页大小
     * @param <T> 泛型类型
     * @return 分页对象
     */
    public static <T> Page<T> createPage(Long current, Long size) {
        // 参数校验
        if (current == null || current < 1) {
            current = DEFAULT_CURRENT;
        }
        if (size == null || size < 1) {
            size = DEFAULT_SIZE;
        }
        if (size > MAX_SIZE) {
            size = MAX_SIZE;
        }
        
        return new Page<>(current, size);
    }

    /**
     * 创建分页对象（使用默认参数）
     * 
     * @param <T> 泛型类型
     * @return 分页对象
     */
    public static <T> Page<T> createPage() {
        return createPage(DEFAULT_CURRENT, DEFAULT_SIZE);
    }

    /**
     * 创建分页对象（从分页查询参数）
     * 
     * @param pageQuery 分页查询参数
     * @param <T> 泛型类型
     * @return 分页对象
     */
    public static <T> Page<T> createPage(PageQuery pageQuery) {
        if (pageQuery == null) {
            return createPage();
        }
        
        Page<T> page = createPage(pageQuery.getCurrent(), pageQuery.getSize());
        
        // 添加排序条件
        if (StringUtils.hasText(pageQuery.getOrderBy())) {
            if ("DESC".equalsIgnoreCase(pageQuery.getOrderDirection())) {
                page.addOrder(com.baomidou.mybatisplus.core.metadata.OrderItem.desc(pageQuery.getOrderBy()));
            } else {
                page.addOrder(com.baomidou.mybatisplus.core.metadata.OrderItem.asc(pageQuery.getOrderBy()));
            }
        }
        
        return page;
    }

    /**
     * 转换为PageResponse
     * 
     * @param page MyBatis-Plus分页对象
     * @param <T> 泛型类型
     * @return PageResponse对象
     */
    public static <T> PageResponse<T> toPageResponse(IPage<T> page) {
        return new PageResponse<>(page);
    }

    /**
     * 转换为PageResponse（带数据转换）
     * 
     * @param page MyBatis-Plus分页对象
     * @param converter 数据转换函数
     * @param <T> 原始数据类型
     * @param <R> 目标数据类型
     * @return PageResponse对象
     */
    public static <T, R> PageResponse<R> toPageResponse(IPage<T> page, Function<T, R> converter) {
        PageResponse<T> originalResponse = new PageResponse<>(page);
        return originalResponse.convert(converter);
    }

    /**
     * 执行分页查询
     * 
     * @param mapper Mapper接口
     * @param pageQuery 分页查询参数
     * @param queryWrapper 查询条件
     * @param <T> 实体类型
     * @return 分页结果
     */
    public static <T> PageResponse<T> executePage(BaseMapper<T> mapper, PageQuery pageQuery, QueryWrapper<T> queryWrapper) {
        try {
            Page<T> page = createPage(pageQuery);
            IPage<T> result = mapper.selectPage(page, queryWrapper);
            return toPageResponse(result);
        } catch (Exception e) {
            log.error("执行分页查询异常: {}", e.getMessage(), e);
            return PageResponse.empty(pageQuery != null ? pageQuery.getCurrent() : DEFAULT_CURRENT, 
                                   pageQuery != null ? pageQuery.getSize() : DEFAULT_SIZE);
        }
    }

    /**
     * 执行分页查询（带数据转换）
     * 
     * @param mapper Mapper接口
     * @param pageQuery 分页查询参数
     * @param queryWrapper 查询条件
     * @param converter 数据转换函数
     * @param <T> 实体类型
     * @param <R> 返回类型
     * @return 分页结果
     */
    public static <T, R> PageResponse<R> executePage(BaseMapper<T> mapper, PageQuery pageQuery, 
                                                    QueryWrapper<T> queryWrapper, Function<T, R> converter) {
        try {
            Page<T> page = createPage(pageQuery);
            IPage<T> result = mapper.selectPage(page, queryWrapper);
            return toPageResponse(result, converter);
        } catch (Exception e) {
            log.error("执行分页查询异常: {}", e.getMessage(), e);
            return PageResponse.<R>empty(pageQuery != null ? pageQuery.getCurrent() : DEFAULT_CURRENT, 
                                   pageQuery != null ? pageQuery.getSize() : DEFAULT_SIZE);
        }
    }

    /**
     * 构建查询条件
     * 
     * @param tenantId 租户ID
     * @param deleted 是否删除
     * @param <T> 实体类型
     * @return 查询条件
     */
    public static <T> QueryWrapper<T> buildBaseQuery(Long tenantId, Boolean deleted) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        
        if (tenantId != null) {
            queryWrapper.eq("tenant_id", tenantId);
        }
        
        if (deleted != null) {
            queryWrapper.eq("deleted", deleted);
        } else {
            // 默认查询未删除的数据
            queryWrapper.eq("deleted", false);
        }
        
        return queryWrapper;
    }

    /**
     * 构建查询条件（默认查询未删除数据）
     * 
     * @param tenantId 租户ID
     * @param <T> 实体类型
     * @return 查询条件
     */
    public static <T> QueryWrapper<T> buildBaseQuery(Long tenantId) {
        return buildBaseQuery(tenantId, false);
    }

    /**
     * 分页查询参数类
     */
    public static class PageQuery {
        /**
         * 当前页码
         */
        private Long current = DEFAULT_CURRENT;

        /**
         * 每页大小
         */
        private Long size = DEFAULT_SIZE;

        /**
         * 排序字段
         */
        private String orderBy;

        /**
         * 排序方向：ASC/DESC
         */
        private String orderDirection = "ASC";

        public Long getCurrent() {
            return current;
        }

        public void setCurrent(Long current) {
            this.current = current;
        }

        public Long getSize() {
            return size;
        }

        public void setSize(Long size) {
            this.size = size;
        }

        public String getOrderBy() {
            return orderBy;
        }

        public void setOrderBy(String orderBy) {
            this.orderBy = orderBy;
        }

        public String getOrderDirection() {
            return orderDirection;
        }

        public void setOrderDirection(String orderDirection) {
            this.orderDirection = orderDirection;
        }

        /**
         * 转换为Page对象
         * 
         * @param <T> 泛型类型
         * @return Page对象
         */
        public <T> Page<T> toPage() {
            return createPage(this);
        }


    }

    /**
     * 分页查询构建器
     * 
     * @param <T> 实体类型
     */
    public static class PageQueryBuilder<T> {
        private final BaseMapper<T> mapper;
        private final QueryWrapper<T> queryWrapper;
        private PageQuery pageQuery;

        public PageQueryBuilder(BaseMapper<T> mapper) {
            this.mapper = mapper;
            this.queryWrapper = new QueryWrapper<>();
        }

        public PageQueryBuilder<T> pageQuery(PageQuery pageQuery) {
            this.pageQuery = pageQuery;
            return this;
        }

        public PageQueryBuilder<T> current(Long current) {
            if (this.pageQuery == null) {
                this.pageQuery = new PageQuery();
            }
            this.pageQuery.setCurrent(current);
            return this;
        }

        public PageQueryBuilder<T> size(Long size) {
            if (this.pageQuery == null) {
                this.pageQuery = new PageQuery();
            }
            this.pageQuery.setSize(size);
            return this;
        }

        public PageQueryBuilder<T> orderBy(String orderBy) {
            if (this.pageQuery == null) {
                this.pageQuery = new PageQuery();
            }
            this.pageQuery.setOrderBy(orderBy);
            return this;
        }

        public PageQueryBuilder<T> orderBy(String orderBy, String direction) {
            if (this.pageQuery == null) {
                this.pageQuery = new PageQuery();
            }
            this.pageQuery.setOrderBy(orderBy);
            this.pageQuery.setOrderDirection(direction);
            return this;
        }

        public PageQueryBuilder<T> eq(String column, Object value) {
            if (value != null) {
                queryWrapper.eq(column, value);
            }
            return this;
        }

        public PageQueryBuilder<T> like(String column, String value) {
            if (StringUtils.hasText(value)) {
                queryWrapper.like(column, value);
            }
            return this;
        }

        public PageQueryBuilder<T> in(String column, List<?> values) {
            if (values != null && !values.isEmpty()) {
                queryWrapper.in(column, values);
            }
            return this;
        }

        public PageQueryBuilder<T> between(String column, Object start, Object end) {
            if (start != null && end != null) {
                queryWrapper.between(column, start, end);
            }
            return this;
        }

        public PageQueryBuilder<T> tenantId(Long tenantId) {
            return eq("tenant_id", tenantId);
        }

        public PageQueryBuilder<T> notDeleted() {
            return eq("deleted", false);
        }

        public PageResponse<T> execute() {
            if (pageQuery == null) {
                pageQuery = new PageQuery();
            }
            return executePage(mapper, pageQuery, queryWrapper);
        }

        public <R> PageResponse<R> execute(Function<T, R> converter) {
            if (pageQuery == null) {
                pageQuery = new PageQuery();
            }
            return executePage(mapper, pageQuery, queryWrapper, converter);
        }
    }

    /**
     * 创建分页查询构建器
     * 
     * @param mapper Mapper接口
     * @param <T> 实体类型
     * @return 分页查询构建器
     */
    public static <T> PageQueryBuilder<T> builder(BaseMapper<T> mapper) {
        return new PageQueryBuilder<>(mapper);
    }
}